package com.users.rn.common.ui

import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.fragment.app.Fragment
import com.users.rn.common.plugin.PluginHelper
import com.users.rn.rncommon.R
import com.users.rn.rncommon.manager.ALHReactActivityDelegate
import com.users.rn.rncommon.manager.ALHReactEnvManager
import com.users.rn.rncommon.manager.ALHReactNativeHost
import com.users.rn.rncommon.model.PluginInfo
import com.users.rn.rncommon.plugin.PluginInformation
import com.users.rn.rncommon.plugin.ReactLoadUtils
import com.users.rn.rncommon.util.RNDebugUtils
import com.users.rn.rncommon.util.RNPageUtil
import com.users.rn.rncommon.util.ReactConst
import com.users.rn.rncommon.util.ReactUtils

/**
RN Fragment
 * 作者：wolf on 1/3/21 17:10

 * 邮箱：bluce

 */

class RNFragment : Fragment() {

    companion object {
        fun getRNFragment(pluginInfo: PluginInfo): RNFragment {
            val fragment = RNFragment()
            val arguments = Bundle()
            arguments.putString(ReactConst.INTENT_KEY_PLUGIN_ID, pluginInfo.pluginId)
            arguments.putString(ReactConst.INTENT_KEY_MODULE_ID, pluginInfo.moduleId)
            arguments.putString(ReactConst.INTENT_KEY_COMPONENT_NAME, pluginInfo.componentName)
            var mParams = pluginInfo.params
            if (pluginInfo.params == null) {
                mParams = Bundle()
            }
            mParams.putString(ReactConst.INTENT_KEY_PAGE_TAG, RNPageUtil.createPageTag(pluginInfo.pluginId, pluginInfo.componentName))
            arguments.putBundle(ReactConst.INTENT_KEY_PARAMS, mParams)
            fragment.arguments = arguments
            return fragment
        }
    }

    lateinit var rnDelegate: ALHReactActivityDelegate
    lateinit var mReactHost: ALHReactNativeHost
    lateinit var debugPluginId: String
    lateinit var pluginInfo: PluginInfo
    lateinit var containerView: FrameLayout

    private fun parseParams(): PluginInfo {
        val pluginId: String = arguments?.getString(ReactConst.INTENT_KEY_PLUGIN_ID)!!
        debugPluginId = if (ReactUtils.getDebugPluginId(activity, pluginId)) {
            pluginId
        } else {
            ""
        }
        val pluginInfo = PluginInfo(
                pluginId,
                arguments?.getString(ReactConst.INTENT_KEY_MODULE_ID),
                arguments?.getString(ReactConst.INTENT_KEY_COMPONENT_NAME),
                arguments?.getBundle(ReactConst.INTENT_KEY_PARAMS),
                PluginHelper.pluginIsPartial(arguments?.getString(ReactConst.INTENT_KEY_PLUGIN_ID)!!),
                ReactUtils.getEventFlag(activity)
        )
        //sdcard bundle version
        val pluginVersion = PluginHelper.getPluginVersion(pluginId)
        //sdcard bundle path
        val pluginDownloadPath = PluginInformation.getPluginPath(pluginId, pluginVersion)
        pluginInfo.setBundlePathAndVersion(pluginDownloadPath, pluginVersion)
        return pluginInfo
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        rnDelegate = ALHReactActivityDelegate(activity)
        pluginInfo = parseParams()
//        if (isDebug()) {
//            mReactHost = ALHReactDebugHostManager.getInstance().get(debugPluginId)
//            rnDelegate.onCreateDelegate(mReactHost, pluginInfo)
//        } else {
        mReactHost = ALHReactEnvManager.getInstance().getReactNativeHost(pluginInfo)
        mReactHost.readyForReactNativeHostListener(pluginInfo, onLoadScriptListener)
        rnDelegate.onFragmentDelegateCreate(mReactHost, pluginInfo)
        //onDelegateCreate方法是将host设置，这个host中的react context是提前预热的，必须在loadBundle方法之前
        ReactLoadUtils.loadBundle(mReactHost, onLoadScriptListener, pluginInfo)
//        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view: View = inflater.inflate(R.layout.rn_fragment_layout, container, false)
        containerView = view.findViewById(R.id.base_rn_fragment_layout)
        return view
    }

    private fun isDebug(): Boolean {
        return debugPluginId.isNotEmpty()
    }

    private fun loadApp() {
        val reactRootView = rnDelegate.loadFragmentApp()
        if (reactRootView != null) {
            containerView.removeAllViews()
            containerView.addView(reactRootView)
        }
    }

    private val onLoadScriptListener = ReactLoadUtils.OnLoadScriptListener { responseStatus: Int, msg: String? ->
        when (responseStatus) {
            ReactConst.LOAD_BUNDLE_SUCCESS -> {
                loadApp()
            }
            ReactConst.LOAD_ASSETS_BIZ_BUNDLE_FAILED -> {
                //如果记载的biz bundle在assets下都找不到，可能是低版本主客调用了高版本才有的rn包
                onDestroy()
            }
            else -> {
                if (isDebug()) {
                    return@OnLoadScriptListener
                }
                ReactUtils.eventBizBundle(activity, pluginInfo, msg)
            }
        }
    }


    override fun onResume() {
        super.onResume()
        if (isDebug()) {
            setDebugIpToSp()
        }
        if (rnDelegate != null) {
            rnDelegate.onResume()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        mReactHost?.removeComponent(pluginInfo.pluginId, pluginInfo.componentName)
    }

    override fun onPause() {
        super.onPause()
        if (rnDelegate != null) {
            rnDelegate.onPause()
        }
    }

    private fun setDebugIpToSp() {
        PreferenceManager.getDefaultSharedPreferences(activity)
                .edit()
                .putString(ReactConst.DEBUG_IP, RNDebugUtils.getDebugIp(activity, debugPluginId))
                .apply()
    }
}